

namespace awa {

template<typename T>
class Singleton {
 public:
  Singleton() {
    assert(Singleton::instane_ == 0);
    Singleton::instance_ = static_cast<T*>(this);
  }
  ~Singleton() {
    Singleton::instance_ = 0;
  }
  static T* Instance();
  static void Destroy();
 private:
  static T* instance_;
  static T* CreateInstance();
  static void ScheduleForDestruction(void (*)());
  static void DestroyInstance(T*);
  inline Singleton(Singleton const&){}
  inline Singleton& operator = (Singleton const&)
    {return *this;}
};


template<typename T>
T*
Singleton<T>::Instance() {
  if(Singleton::instance_ == 0)
    {
      Singleton::instance_ = CreateInstance();
      ScheduleForDestruction(Singleton::Destroy);
    }
  return Singleton::instance_;
}

template<typename T>
void
Singleton<T>::Destroy() {
  if(Singleton::instance_ != 0)
    {
      DestroyInstance(Singleton::instance_);
      Singleton::instance_ = 0;
    }
}

template<typename T>
T*
Singleton<T>::CreateInstance() {
  return new T(*T::instanceCreationHook());
}

template<typename T>
inline void Singleton<T>::ScheduleForDestruction(void (*pFun)()) {
  atexit(pFun);
}

template<typename T>
inline void Singleton<T>::DestroyInstance(T* p) {
  delete p;
}

template<typename T>
T* Singleton<T>::instance_ = 0;

}; // end of namespace awa
